package com.hr.shiro.realm;

import com.fasterxml.jackson.databind.annotation.JsonAppend;
import com.hr.entity.AoaSysMenu;
import com.hr.entity.AoaUser;
import com.hr.feign.user.OaUserFeignService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * 自定义实现的简单Realm,它必须继承 AuthorizingRealm（授权的Realm）类
 */
public class SimpleRealm extends AuthorizingRealm {

    @Autowired
    private OaUserFeignService userFeignService;
    /**
     * 权限获取方法,获取指定身份的权限，并返回相关信息
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        /**
         * 身份认证成功后的 User 对象就存储在这个 primaryPrincipal 属性中
         * 直接拿出来强转即可
         */
        AoaUser user = (AoaUser)principalCollection.getPrimaryPrincipal();
        //角色ID
        Long roleId = user.getRoleId();
        //TODO 根据角色id 查询该用户拥有操作哪些菜单的权限
        ResponseEntity<List<AoaSysMenu>> resp = userFeignService.queryListByRoleId(roleId);
        List<AoaSysMenu> menuList = resp.getBody();

        //用户存储该用户的 权限信息对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if(menuList != null){
            for (AoaSysMenu menu : menuList) {
                //如果permission 不为空，我们就将其加入到此用户的权限列表中
                if(menu.getPermission() != null &&
                !menu.getPermission().isEmpty()){
                    //添加权限
                    info.addStringPermission(menu.getPermission());
                }
            }
//            menuList.forEach((menu)->{
//                //添加权限
//                info.addStringPermission(menu.getPermission());
//            });
        }
        //返回我们设置好的该用户权限信息对象
        return info;
    }

    /**
     * 本案例中 测试用户为：张三
     * 身份验证方法,验证账户和密码，并返回相关信息
     * @param authcToken 认证的token（通行令）
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        //Shiro 表单认证的 token实现类就是 它 -- UsernamePasswordToken，直接强转即可
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        //获取用户输入的 用户名
        String userName = token.getUsername();
        /**
         * TODO 用户输入的密码，我们的代码用不到此密码，
         * 我写在这里是告诉同学们shiro可以通过此token对象拿到用户输入的密码
         */
        String inputPassword = new String(token.getPassword());
        //根据用户名 查询出用户信息
        ResponseEntity<AoaUser> resp = userFeignService.queryByUserName(userName);
        AoaUser user = resp.getBody();
        if(user == null){
            //找不到用户
            throw new RuntimeException("*** 找不到用户");
        }

        /**
         * 创建一个简单的 存储认证信息的 类对象
         * 参数1：用户对象
         * 参数2：数据库中该用户的密码
         * 参数3：实现该认证的realm的名称
         */
        return new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
    }
}